package org.luxor.commons.redis.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.luxor.commons.redis.annotation.RedisCacheable;
import org.luxor.commons.redis.client.RedisObjectClient;
import org.luxor.commons.redis.component.KeyGenerator;
import org.luxor.commons.redis.component.RedisKeys;
import org.luxor.commons.redis.component.ReflectUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Redis缓存加载AOP
 *
 * @author chenshun
 * @email sunlightcs@gmail.com
 * @date 2017-07-17 23:30
 */
@Aspect
public class CacheableAspect {
    private static final Logger logger = LoggerFactory.getLogger(CacheableAspect.class);

    private RedisObjectClient redisObjectClient;

    public void setRedisClientObject(RedisObjectClient redisObjectClient) {
        this.redisObjectClient = redisObjectClient;
    }

    /**
     * 定义缓存逻辑
     */
    @Around("@annotation(org.luxor.commons.redis.annotation.RedisCachePut)")
    public Object cache(ProceedingJoinPoint pjp) throws Throwable {
        //获取所有参数
        RedisCacheable redisCacheable = ReflectUtil.getMethod(pjp).getAnnotation(RedisCacheable.class);
        String fieldKey = KeyGenerator.INSTANCE.getCacheKeyName(pjp, redisCacheable);
        fieldKey = RedisKeys.buildCacheKey(fieldKey);

        //获取方法的返回类型,让缓存可以返回正确的类型
        Class returnType = ((MethodSignature) pjp.getSignature()).getReturnType();

        // 从缓存中获取数据
        Object result = redisObjectClient.get(fieldKey, returnType);
        if (result == null) {
            result = pjp.proceed();
            redisObjectClient.set(fieldKey, result, redisCacheable.expireTime());
        } else {
            logger.info("The data returned is from Redis( @RedisCachePut ). CacheKey:[{}] ", fieldKey);
        }
        return result;
    }

}